﻿using System;

namespace OperatorOverLoading
{
    class Program
    {
        static void Main(string[] args)
        {
            Student s1 = new Student(20, "Tom");
            Student s2 = new Student(18, "Jack");
            Student s3 = s1 + s2;

            s3.SayPlus();
            (s1 - s2).SayMinus();
            Console.ReadKey();
        }
    }

    public class Student
    {
        private string name;
        private int age;

        public Student()
        {

        }

        public Student(int age, string name)
        {
            this.name = name;
            this.age = age;
        }

        public void SayPlus()
        {
            Console.WriteLine("{0} 年龄之和为：{1}", name, age);
        }

        public void SayMinus()
        {
            Console.WriteLine("{0} 年龄之差为：{1}", name, age);
        }

        // 覆盖“+”操作符
        public static Student operator +(Student s1, Student s2)
        {
            return new Student(s1.age + s2.age, s1.name + " And " + s2.name);
        }

        // 覆盖“-”操作符
        public static Student operator -(Student s1, Student s2)
        {
            return new Student(Math.Abs(s1.age - s2.age), s1.name + " And " + s2.name);
        }
    }
}
/*
 
operator 关键字用于在类或结构声明中声明运算符。运算符声明可以采用下列四种形式之一：

public static result-type operator unary-operator ( op-type operand )
public static result-type operator binary-operator ( op-type operand, op-type2 operand2 )
public static implicit operator conv-type-out ( conv-type-in operand )
public static explicit operator conv-type-out ( conv-type-in operand )
参数：

 result-type 运算符的结果类型。
 unary-operator 下列运算符之一：+ - ! ~ ++ — true false
 op-type 第一个（或唯一一个）参数的类型。
 operand 第一个（或唯一一个）参数的名称。
 binary-operator 其中一个：+ - * / % & | ^ << >> == != > < >= <=
 op-type2 第二个参数的类型。
 operand2 第二个参数的名称。
 conv-type-out 类型转换运算符的目标类型。
 conv-type-in 类型转换运算符的输入类型。
注意：

前两种形式声明了用户定义的重载内置运算符的运算符。并非所有内置运算符都可以被重载（请参见可重载的运算符）。op-type 和 op-type2 中至少有一个必须是封闭类型（即运算符所属的类型，或理解为自定义的类型）。例如，这将防止重定义整数加法运算符。

后两种形式声明了转换运算符。conv-type-in 和 conv-type-out 中正好有一个必须是封闭类型（即，转换运算符只能从它的封闭类型转换为其他某个类型，或从其他某个类型转换为它的封闭类型）。

运算符只能采用值参数，不能采用 ref 或 out 参数。

C# 要求成对重载比较运算符。如果重载了==，则也必须重载!=，否则产生编译错误。同时，比较运算符必须返回bool类型的值，这是与其他算术运算符的根本区别。

C# 不允许重载=运算符，但如果重载例如+运算符，编译器会自动使用+运算符的重载来执行+=运算符的操作。

运算符重载的其实就是函数重载。首先通过指定的运算表达式调用对应的运算符函数，然后再将运算对象转化为运算符函数的实参，接着根据实参的类型来确定需要调用的函数的重载，这个过程是由编译器完成。

任何运算符声明的前面都可以有一个可选的属性（C# 编程指南）列表。
 
 */